using System;
using System.Collections;
using System.Data;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using PHSRAG.Insight21.Common.Pages;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.InsightWebControls;
using PHSRAG.Insight21.Personnel;
using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.SearchContext;
using PHSRAG.Utility;
using PHSRAG.WebControls;
using Constants=PHSRAG.Insight21.InsightUtilities.Constants;
using PersonnelConstants = PHSRAG.Insight21.Personnel.Constants;

namespace PHSRAG.Insight21
{
    /// <summary>
    /// The SalaryGrid class supports the SalaryGrid.aspx page.
    /// It displays the salary sources for the selected group of employee's or
    /// one employee at a time across the identified categories of accounts.
    /// It also allows the user to drill down to the personnel details page.
    /// </summary>
    /// <remarks>
    /// The SalaryGrid page supports searching/filtering the Salary Grid data
    /// based on user-defined and user-selectable search criteria.
    /// Following is the list of such criteria:
    /// <list type="bullet">
    /// <item><description>Employee Last Name (free-form entry)</description></item>
    /// <item><description>Employee First Name (free-form entry)</description></item>
    /// <item><description>PI (select from a DataGrid)</description></item>
    /// <item><description>Lab (select from a DataGrid)</description></item>
    /// <item><description>Employee Number (free-form entry)</description></item>
    /// <item><description>Job Code (free-form entry)</description></item>
    /// <item><description>Status (select from a drop-down list)</description></item>
    /// <item><description>HR Department (select from a drop-down list)</description></item>
    /// <item><description>Pay Frequency type (select from a drop-down list)</description></item>
    /// <item><description>Effective Salary Date From/To (select both from a calender)</description></item>
    /// <item><description>Fiscal Year (select from a drop-down list)</description></item>
    /// </list>
    /// </remarks>
    public partial class SalaryGrid : NoCachePage
    {
        # region Constants

        private const string CurrentPageIndexKey = "CurrentPageIndex_949D1920-8CB1-4B13-9774-7D0743484DF7";
        private const int DataRowIndex = 0;
        private const int DefaultID = 0;
        private const string ExcelReportControlFilePath = "../../Personnel/Reports/SalaryGridExcel.ascx";
        private const int FirstChildControlIndex = 0;
        private const string FiscalYearKey = "FiscalYearKey_949D1920-8CB1-4B13-9774-7D0743484DF7";
        private const string JobMapIdKey = "JobMapIdKey_949D1920-8CB1-4B13-9774-7D0743484DF7";
        private const string SalaryTotalsTableName = "SalaryTotals";
        private const string SearchCriteriaVersionKey = "SearchCriteriaVersion_949D1920-8CB1-4B13-9774-7D0743484DF7";
        private const string ViewByFiscalYear = "viewByFiscalYear";

        #endregion

        private void OnSubHeaderNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        private void OnBreadCrumbNavigate(object sender, CommandEventArgs e)
        {
            PurgeCache();
        }

        public void PurgeCache()
        {
            ResultsCache.PurgeObject(cachePolicy);
        }

        #region Nested type: SalaryTotalsColumn

        private enum SalaryTotalsColumn
        {
            CurrentSalary,
            TotalSalary,
            ResearchGrant,
            ResearchSundry,
            Discretionary,
            OperatingFunds,
            POFunds,
            HMSFunds,
            VA,
            Other
        }

        #endregion

        #region Instance Variables (Private)

        private ICachePolicy cachePolicy;
        private ICachePolicy pageCachePolicy;

        #endregion

        #region Enumerations (Private)

        /// <summary>
        /// The DataGridColumns enumeration defines values 
        /// for indexing columns in the datagrid.
        /// </summary>
        private enum DataGridColumns
        {
            EmployeeJobMapId,
            EmployeeName,
            CurrentTitle,
            CurrentSalary,
            TotalSalary,
            ResearchGrant,
            ResearchSundry,
            Discretionary,
            OperatingFunds,
            POFunds,
            HMSFunds,
            VA,
            Other
        }

        /// <summary>
        /// The SalaryTotalsColumn defines values for indexing columns , 
        /// used in computing the Salary totals.
        /// </summary>
        //		public enum SalaryTotalsColumn
        //		{
        //			CurrentSalary,
        //			TotalSalary,
        //			ResearchGrant ,
        //			ResearchSundry ,
        //			Discretionary ,
        //			OperatingFunds ,
        //			POFunds,
        //			HMSFunds,
        //			VA,	
        //			Other 
        //		}

        #endregion

        #region Private Properties

        /// <summary>
        /// Gets/Sets  the Fiscal Year. The fiscal year is cached.
        /// </summary>
        private int FiscalYear
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SalaryGridPageKey) as Hashtable;
                return (h == null || h[Keys.FiscalYearIDKey] == null) ? DefaultID : (int) h[Keys.FiscalYearIDKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SalaryGridPageKey) as Hashtable ?? new Hashtable();
                h[Keys.FiscalYearIDKey] = value;
                pageCachePolicy.Cache(Keys.SalaryGridPageKey, h);
            }
        }

        /// <summary>
        /// Get the Salary Grid informations that the logged-in user has access to. The list of Salary Grids data is
        /// is maintained by the PersonnelSalaries business object within its data container. This object is cached.
        /// </summary>
        private PersonnelSalaries PersonnelSalariesInstance
        {
            get
            {
                PersonnelSalaries personnelSalaries =
                    ResultsCache.GetObject(cachePolicy, PersonnelSalaries.CacheKey) as PersonnelSalaries;

                if (personnelSalaries == null)
                {
                    personnelSalaries = new PersonnelSalaries();
                    personnelSalaries.Load(DataAccess.GetConnectionString()
                        , ((UserContext) cachePolicy.GetCachedObject(UserContext.CacheKey)).DomainUserId
                        , FiscalYear
                        , JobMapId);
                    ResultsCache.SetObject(cachePolicy, PersonnelSalaries.CacheKey, personnelSalaries);
                }

                return personnelSalaries;
            }
        }

        /// <summary>
        /// Get/set the current page index. 
        /// </summary>
        /// <remarks>
        /// Private int property used to get/set the current page index.  
        /// This property sets the dataGrid.CurrentPageIndex property.
        /// This and All properties required to re-establish the page are stored as name / value pairs in
        /// a hash table stored in the session cache under the key Keys.SalaryGridPageKey.  
        /// This enables the page to re-establish its state with minimal IO to what it was when
        /// the user last visited it.
        ///</remarks>
        private int CurrentPageIndex
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SalaryGridPageKey) as Hashtable;
                return (h == null || h[CurrentPageIndexKey] == null) ? 0 : (int) h[CurrentPageIndexKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SalaryGridPageKey) as Hashtable ?? new Hashtable();
                h[CurrentPageIndexKey] = value;
                salaryGridDetails.CurrentPageIndex = value;
                pageCachePolicy.Cache(Keys.SalaryGridPageKey, h);
            }
        }

        /// <summary>
        /// Get/Set the Employee Job Map ID for which the details information has to be retrieved.
        /// </summary>
        private int JobMapId
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SalaryGridPageKey) as Hashtable;
                return (h == null || h[Keys.EmployeeJobMapIDKey] == null) ? DefaultID : (int) h[Keys.EmployeeJobMapIDKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SalaryGridPageKey) as Hashtable ?? new Hashtable();
                h[Keys.EmployeeJobMapIDKey] = value;
                pageCachePolicy.Cache(Keys.SalaryGridPageKey, h);
            }
        }

        /// <summary>
        /// Gets/sets an integer value indicating the search criteria version. 
        /// The version number changes when the search criteria changes.  This signals the page to re-build its
        /// cache.
        /// </summary>
        private int SearchCriteriaVersion
        {
            get
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SalaryGridPageKey) as Hashtable;
                return (h == null || h[SearchCriteriaVersionKey] == null) ? 0 : (int) h[SearchCriteriaVersionKey];
            }
            set
            {
                Hashtable h = pageCachePolicy.GetCachedObject(Keys.SalaryGridPageKey) as Hashtable ?? new Hashtable();

                h[SearchCriteriaVersionKey] = value;
                pageCachePolicy.Cache(Keys.SalaryGridPageKey, h);
            }
        }

        #endregion

        #region Constructors

        #endregion

        #region event handlers

        #region PageLoad

        /// <summary>
        /// Re-establishes the page context in between postbacks.
        /// Case1: If user navigages from Personnel Summary Page,
        /// the breadcrumb level is set accordingly and 
        /// IncomingData is stored in the viewstate and the IncomingData is removed from the cache.
        /// Case2: If user navigates from Module menu, set the breadcrumb level 
        /// and remove the salary data instance from the cache.
        /// Load the salary Grid data and initialize the pager control.
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">System.EventArgs</param>
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                annunciator.Message = string.Empty;
                annunciator.Title = string.Empty;

                Hashtable dictionary = pageCachePolicy.GetCachedObject(Keys.IncomingDataKey) as Hashtable;
                reportDownload.SQLReportName = SSRSRequest.ReportNames.Personnel.SalaryGrid; //"Personnel_SalaryGrid" 

                if (IsPostBack)
                {
                    ManagePagination();
                    LoadDataGrid();
                }
                else
                {
                    ((ExpansionToggler) expandingPanel.FindControl("expansionToggler")).HelpText =
                        Constants.SearchHelpText;

                    expandingPanel.IsExpanded = true;

                    breadCrumb.Add("Salary Grid", Settings.
                        GetKeyValue("SubNavigation.Personnel.SalaryGridURL", string.Empty)
                        , (dictionary != null && dictionary.ContainsKey(Keys.EmployeeJobMapIDKey))
                            ? PersonnelConstants.DefaultDetailsPageRank : PersonnelConstants.DefaultSummaryPageRank);

                    salaryGridDetails.PageSize =
                        Settings.GetKeyValue(PersonnelConstants.DataGridPageSizeKey
                            , PersonnelConstants.DefaultDatagridPageSize);

                    if (dictionary != null && dictionary.ContainsKey(Keys.EmployeeJobMapIDKey))
                    {
                        ResultsCache.PurgeObject(cachePolicy);

                        JobMapId = ((int) dictionary[Keys.EmployeeJobMapIDKey] == 0)
                            ? 0 : (int) dictionary[Keys.EmployeeJobMapIDKey];
                        pageCachePolicy.UnCache(Keys.IncomingDataKey);
                    }
                    else
                    {
                        //Reset the job map id to the default
                        JobMapId = DefaultID;
                    }
                    ProcessSearch();
                    personnelSubNavigation.SelectedLink = PersonnelSubNavigation.salaryGridCommand;

                    hiddenSearchCriteria.Value = HttpUtility.UrlEncode(AddRefreshDatesToCriteria(((CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey)).GetSearchCriteria(Page.Request.Url.ToString())));
                }
            }
            catch (Exception ex)
            {
                salaryGridDetails.Visible = pagerBelowDatagrid.Visible = pagerAboveDatagrid.Visible = reportDownload.Visible = false;
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #endregion

        # region Paging

        /// <summary>
        /// Handler for the event raised when the FirstPage link is clicked in the Pager control.
        /// Set the current page index to 0, bind the datagrid with data and manage navigation links.
        /// To avoid superfluous data binding activites, no action is taken if the current page index is already 0.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnFirstPage(object sender, CommandEventArgs e)
        {
            CurrentPageIndex = 0;
            LoadDataGrid();
        }

        /// <summary>
        /// OnPreviousPage event is fired when user clicks on the Previous Page in the Pager control.
        ///  If the current page is greater than 0, subtracts 1 page from the current page index, 
        /// Loads the salary grid data and sets  the navigational links accordingly.
        /// </summary>
        /// <param name="sender">object</param>
        /// <param name="e">CommandEventArgs</param>
        private void OnPreviousPage(object sender, CommandEventArgs e)
        {
            --CurrentPageIndex;
            LoadDataGrid();
        }

        /// <summary>
        /// Handler for the event raised when the NextPage link is clicked in the Pager control.
        /// Increment the current page index, bind the datagrid with data and manage navigation links.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnNextPage(object sender, CommandEventArgs e)
        {
            ++CurrentPageIndex;
            LoadDataGrid();
        }

        /// <summary>
        /// Handler for the event raised when the LastPage link is clicked in the Pager control.
        /// Set the current page index to one less than the total page count (index is 0-based), bind the datagrid with
        /// data and manage navigation links.
        /// To avoid superfluous data binding activites, no action is taken if the current 
        /// page index is already corresponding to the last page.
        /// </summary>
        /// <param name="sender">Control which rasied the event</param>
        /// <param name="e">Arguments associated with the event</param>
        private void OnLastPage(object sender, CommandEventArgs e)
        {
            CurrentPageIndex = pagerAboveDatagrid.PageCount - 1;
            LoadDataGrid();
        }

        # endregion

        # region Search

        /// <summary>
        /// Handler for the event raised when the Search button is clicked in the Search control.
        /// Gets the search criteria and performs a search. The actual search is performed by the PersonnelSalaries object
        /// which returns true if it did indeed apply any filteration criteria, and false otherwise. This predicate
        /// is used by LoadDataGrid() to control the visibility of the pager controls.
        /// If the selected Fiscal Year is changed, the existing Salary grid instance is uncached 
        /// and the salary grid data is reloaded.
        /// </summary>
        /// <param name="args">Search Criteria args associated with the search event</param>
        protected void OnSearch(SearchCriteriaArgs args)
        {
            ProcessSearch();
        }

        /// <summary>
        /// Handler for the event raised when the "Clear Selection" button is clicked on the page.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void OnClearSelection(object sender, CommandEventArgs e)
        {
            //added the code to fix the problem with the search if it comes from the Personnel Summary page
            //it did not help at all.
            CommonSearchContext searchContext =
                cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
            searchContext.Reset(Page.Request.Url.ToString());
            searchContext.GetSearchCriteria(Page.Request.Url.ToString()).Clear();
            ProcessSearch();
            JobMapId = 0;

            salaryGridDetails.Visible = false;
            pagerAboveDatagrid.Visible = pagerBelowDatagrid.Visible = reportDownload.Visible = false;
        }

        #endregion

        #region DataGrid Events

        /// <summary>
        /// Handler for event raised while each data grid item is created.
        /// Help in putting the symbol denoting the sort column in the data grid.
        /// If the item being created is the data grid header:
        /// <list type="bullet">
        /// <item><description>Get the sort column and sort order from the PersonnelSalaries instance in the cache</description></item>
        /// <item><description>Create a Hashtable of column indices, keyed by the sort expression of each column</description></item>
        /// <item><description>Using the hash table add a label with sort symbol to the column on which sort has happened</description></item>
        /// </list>
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemCreated(object sender, DataGridItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Header)
            {
                PersonnelSalaries personnelSalaries = PersonnelSalariesInstance;
                Label sortSymbol = new Label();
                sortSymbol.Text = personnelSalaries.SortAscending ? Constants.SortAscendingText : Constants.SortDescendingText;
                sortSymbol.Font.Name = Constants.SortSymbolFontName;

                Hashtable columnMap = new Hashtable();
                foreach (DataGridColumn column in salaryGridDetails.Columns)
                {
                    columnMap[column.SortExpression] = salaryGridDetails.Columns.IndexOf(column);
                }

                string sortColumn = personnelSalaries.SortColumn;
                if (columnMap.ContainsKey(sortColumn))
                {
                    (e.Item.Cells[(int) columnMap[sortColumn]]).Controls.Add(sortSymbol);
                }
            }
        }

        /// <summary>
        /// Handler for the event raised when a column header within the data grid is clicked.
        /// Set the currentpageindex to 0 as sorting need to be done on all records and not only on what is visible
        /// Load the data grid and intialize the pager controls
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnSort(object sender, DataGridSortCommandEventArgs e)
        {
            if (e.SortExpression != string.Empty)
            {
                PersonnelSalariesInstance.Sort(e.SortExpression);
                CurrentPageIndex = 0;
                LoadDataGrid();
            }
        }

        /// Handler for the event raised when a row in the datagrid is databound.
        /// Check for the amounts less than or equal to zero and format the salary grid columns accordingly.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnItemDataBound(object sender, DataGridItemEventArgs e)
        {
            try
            {
                if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
                {
                    // Research Grant Column
                    TableCell amount = e.Item.Cells[(int) DataGridColumns.ResearchGrant];
                    decimal fundAmount = Convert.ToDecimal(((LinkButton) amount.Controls[FirstChildControlIndex]).Text);
                    if (fundAmount <= 0)
                    {
                        ConvertLinkToText(amount);
                    }
                    else
                    {
                        ((LinkButton) amount.Controls[FirstChildControlIndex]).Text = fundAmount.ToString("c");
                    }
                    // ResearchSundry column.
                    amount = e.Item.Cells[(int) DataGridColumns.ResearchSundry];
                    fundAmount = Convert.ToDecimal(((LinkButton) amount.Controls[FirstChildControlIndex]).Text);
                    if (fundAmount <= 0)
                    {
                        ConvertLinkToText(amount);
                    }
                    else
                    {
                        ((LinkButton) amount.Controls[FirstChildControlIndex]).Text = fundAmount.ToString("c");
                    }
                    // Discretionary column.
                    amount = e.Item.Cells[(int) DataGridColumns.Discretionary];
                    fundAmount = Convert.ToDecimal(((LinkButton) amount.Controls[FirstChildControlIndex]).Text);
                    if (fundAmount <= 0)
                    {
                        ConvertLinkToText(amount);
                    }
                    else
                    {
                        ((LinkButton) amount.Controls[FirstChildControlIndex]).Text = fundAmount.ToString("c");
                    }
                    // Operating Funds column.
                    amount = e.Item.Cells[(int) DataGridColumns.OperatingFunds];
                    fundAmount = Convert.ToDecimal(((LinkButton) amount.Controls[FirstChildControlIndex]).Text);
                    if (fundAmount <= 0)
                    {
                        ConvertLinkToText(amount);
                    }
                    else
                    {
                        ((LinkButton) amount.Controls[FirstChildControlIndex]).Text = fundAmount.ToString("c");
                    }
                    // PO  Funds column.
                    amount = e.Item.Cells[(int) DataGridColumns.POFunds];
                    fundAmount = Convert.ToDecimal(((LinkButton) amount.Controls[FirstChildControlIndex]).Text);
                    if (fundAmount <= 0)
                    {
                        ConvertLinkToText(amount);
                    }
                    else
                    {
                        ((LinkButton) amount.Controls[FirstChildControlIndex]).Text = fundAmount.ToString("c");
                    }
                    // HMS  Funds column.
                    amount = e.Item.Cells[(int) DataGridColumns.HMSFunds];
                    fundAmount = Convert.ToDecimal(((LinkButton) amount.Controls[FirstChildControlIndex]).Text);
                    if (fundAmount <= 0)
                    {
                        ConvertLinkToText(amount);
                    }
                    else
                    {
                        ((LinkButton) amount.Controls[FirstChildControlIndex]).Text = fundAmount.ToString("c");
                    }
                    // VA  Funds column.
                    amount = e.Item.Cells[(int) DataGridColumns.VA];
                    fundAmount = Convert.ToDecimal(((LinkButton) amount.Controls[FirstChildControlIndex]).Text);
                    if (fundAmount <= 0)
                    {
                        ConvertLinkToText(amount);
                    }
                    else
                    {
                        ((LinkButton) amount.Controls[FirstChildControlIndex]).Text = fundAmount.ToString("c");
                    }
                    // Other  Funds column.
                    amount = e.Item.Cells[(int) DataGridColumns.Other];
                    fundAmount = Convert.ToDecimal(((LinkButton) amount.Controls[FirstChildControlIndex]).Text);
                    if (fundAmount <= 0)
                    {
                        ConvertLinkToText(amount);
                    }
                    else
                    {
                        ((LinkButton) amount.Controls[FirstChildControlIndex]).Text = fundAmount.ToString("c");
                    }
                }
                    //Load the totals in the footer.
                else if (e.Item.ItemType == ListItemType.Footer)
                {
                    try
                    {
                        DataTable totalsTable = PersonnelSalariesInstance.GetDataContainer().Tables[SalaryTotalsTableName];
                        DataRow row = totalsTable.Rows[DataRowIndex];
                        e.Item.Cells[(int) DataGridColumns.EmployeeName].Text = "Total";
                        e.Item.Cells[(int) DataGridColumns.CurrentSalary].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.CurrentSalary]).ToString("c");
                        e.Item.Cells[(int) DataGridColumns.TotalSalary].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.TotalSalary]).ToString("c");
                        e.Item.Cells[(int) DataGridColumns.ResearchGrant].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.ResearchGrant]).ToString("c");
                        e.Item.Cells[(int) DataGridColumns.ResearchSundry].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.ResearchSundry]).ToString("c");
                        e.Item.Cells[(int) DataGridColumns.Discretionary].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.Discretionary]).ToString("c");
                        e.Item.Cells[(int) DataGridColumns.OperatingFunds].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.OperatingFunds]).ToString("c");
                        e.Item.Cells[(int) DataGridColumns.POFunds].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.POFunds]).ToString("c");
                        e.Item.Cells[(int) DataGridColumns.HMSFunds].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.HMSFunds]).ToString("c");
                        e.Item.Cells[(int) DataGridColumns.VA].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.VA]).ToString("c");
                        e.Item.Cells[(int) DataGridColumns.Other].Text = Convert.ToDecimal(row[(int) SalaryTotalsColumn.Other]).ToString("c");
                    }
                    catch (Exception ex)
                    {
                        Utility.ExceptionReport.WriteToEventLog("Salary Grid", ex,
                            true, Utility.ExceptionReport.ReportType.Error);
                        annunciator.Message = "Error occurred while computing Salary Grid Totals.";
                    }
                }
            }
            catch (Exception ex)
            {
                Utility.ExceptionReport.WriteToEventLog("Salary Grid", ex,
                    true, Utility.ExceptionReport.ReportType.Error);
                annunciator.Message = "Error occurred while attempting to format columns.";
            }
        }

        /// <summary>
        /// Handler for the event raised when a row in the datagrid is clicked upon.
        /// If the "EmployeeId" was clicked upon (its CommandName is "SelectEmployee"), load the PersonnelDetails page
        /// If the funds have links associated with it, then on clicking upon, loads the Personnel Details page.
        /// In both the cases the page passes the selected employee's jobmapid and Fiscal Year Id through a dictionary.
        /// </summary>
        /// <param name="sender">Control which raised the event</param>
        /// <param name="e">Argument associated with the event</param>
        private void OnDataGridItemCommand(object sender, DataGridCommandEventArgs e)
        {
            try
            {
                if ((e.Item.ItemType == ListItemType.Item) || (e.Item.ItemType == ListItemType.AlternatingItem))
                {
                    if (e.CommandName == "SelectEmployee")
                    {
                        Hashtable dictionary = new Hashtable();
                        dictionary.Add(Keys.EmployeeJobMapIDKey,
                            Convert.ToInt32(e.Item.Cells[(int) DataGridColumns.EmployeeJobMapId].Text));

                        dictionary.Add(Keys.FiscalYearIDKey, FiscalYear);

                        pageCachePolicy.Cache(Keys.IncomingDataKey, dictionary);
                        PurgeCache();
                        Response.Redirect
                            (Settings.GetKeyValue("Other.Personnel.PersonnelDetailsURL", string.Empty), false);
                    }
                }
            }
            catch (Exception ex)
            {
                Utility.ExceptionReport.WriteToEventLog("Salary Grid", ex,
                    true, Utility.ExceptionReport.ReportType.Error);
                annunciator.Message = string.Format
                    ("Error while attempting to navigate for {0} click", e.CommandName);
            }
        }

        # endregion

        #region Header

        /// <summary>
        /// Resets the subnavigation selected link(s) before the 
        /// header performs a redirect.
        /// </summary>
        /// <param name="sender">Control which rasied the event.</param>
        /// <param name="e">Arguments associated with the event.</param>
        private void OnHeaderNavigate(object sender, CommandEventArgs e)
        {
            personnelSubNavigation.Reset();
            PurgeCache();
        }

        #endregion

        #endregion

        #region Private Methods

        /// <summary>
        /// Load the datagrid with sufficient data for display within one page of the data grid. This is done as follows:
        /// Get the salary information for all personnel that the user has access to for the selected fiscal year. 
        /// Use that to initialize the data grid and
        /// the pager controls based on the page size of the data grid.
        /// The pagers are made visible only when more than one page of data can be displayed.
        /// If there is no data to display, warn the user via the annunciator.
        /// </summary>
        private void LoadDataGrid()
        {
            try
            {
                PersonnelSalaries personnelSalaries = PersonnelSalariesInstance;

                salaryGridDetails.VirtualItemCount = pagerAboveDatagrid.RecordCount
                    = pagerBelowDatagrid.RecordCount = personnelSalaries.Count;

                int currentPageIndex = CurrentPageIndex;
                int pageCount = (pagerAboveDatagrid.RecordCount/salaryGridDetails.PageSize) +
                    (((pagerAboveDatagrid.RecordCount%salaryGridDetails.PageSize) == 0) ? 0 : 1);
                pagerBelowDatagrid.PageCount = pagerAboveDatagrid.PageCount = pageCount;
                pagerBelowDatagrid.CurrentPage = pagerAboveDatagrid.CurrentPage = currentPageIndex + 1;

                salaryGridDetails.DataSource = personnelSalaries.GetSalaryGridList
                    (currentPageIndex*salaryGridDetails.PageSize, salaryGridDetails.PageSize);
                salaryGridDetails.DataBind();

                salaryGridDetails.Visible = pagerBelowDatagrid.Visible = pagerAboveDatagrid.Visible = reportDownload.Visible =
                    (salaryGridDetails.Items.Count > 0);
                if (pagerAboveDatagrid.Visible)
                {
                    ManagePagination();
                }
                else
                {
                    annunciator.Message = "No salary data found for user";
                }
            }
            catch (Exception ex)
            {
                salaryGridDetails.Visible = pagerBelowDatagrid.Visible = pagerAboveDatagrid.Visible = reportDownload.Visible = false;
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        /// <summary>
        /// Manages the pagination logic.
        /// Set the First record and last record values for the pager controls
        /// based on the current page index and the data grid page size respectively
        /// </summary>
        private void ManagePagination()
        {
            int currentPageIndex = CurrentPageIndex;
            salaryGridDetails.CurrentPageIndex = currentPageIndex;

            int startIndex = currentPageIndex*salaryGridDetails.PageSize;

            pagerBelowDatagrid.FirstRecord = pagerAboveDatagrid.FirstRecord = startIndex + 1;
            pagerBelowDatagrid.LastRecord = pagerAboveDatagrid.LastRecord =
                Math.Min(startIndex + salaryGridDetails.PageSize, salaryGridDetails.VirtualItemCount);

            pagerBelowDatagrid.EnableFirstPage = pagerAboveDatagrid.EnableFirstPage =
                pagerBelowDatagrid.EnablePreviousPage = pagerAboveDatagrid.EnablePreviousPage =
                    (CurrentPageIndex != 0);

            pagerBelowDatagrid.EnableLastPage = pagerAboveDatagrid.EnableLastPage =
                pagerBelowDatagrid.EnableNextPage = pagerAboveDatagrid.EnableNextPage =
                    (CurrentPageIndex != (pagerAboveDatagrid.PageCount - 1));
        }

        /// <summary>
        /// ConvertLinkToText method replaces the link button column to literal control, 
        /// when the cell value is less than or equal to zero.
        /// </summary>
        /// <param name="amount">Grid cell value.</param>
        private void ConvertLinkToText(TableCell amount)
        {
            string dataValue = ((LinkButton) amount.Controls[FirstChildControlIndex]).Text;
            amount.Controls.Clear();
            amount.Controls.Add(new LiteralControl(Convert.ToDecimal(dataValue).ToString("c")));
        }

        /// <summary>
        /// Adds refresh dates currently visible on the page to the search criteria string
        /// to be passed down to reports. The criteria does not persist to the SearchCriteria
        /// object.
        /// </summary>
        /// <param name="searchCriteria">Object containing search criteria.</param>
        /// <returns>A string representation of search criteria. </returns>
        private string AddRefreshDatesToCriteria(SearchCriteria searchCriteria)
        {
            StringBuilder criteria = new StringBuilder(searchCriteria.ToString(";"));
            if (refreshDates.SalaryAsOfDateVisible)
            {
                criteria.AppendFormat("Last Salary Post|{0};", refreshDates.SalaryAsOfDate.ToShortDateString());
            }
            if (refreshDates.GLAsOfDateVisible)
            {
                criteria.AppendFormat("Last GL Post|{0};", refreshDates.GLPostAsOfDate.ToShortDateString());
            }
            if (refreshDates.POAPAsOfDateVisible)
            {
                criteria.AppendFormat("Last PO/AP Post|{0};", refreshDates.POAPAsOfDate.ToShortDateString());
            }
            return criteria.ToString();
        }

        /// <summary>
        /// Search the summary data for the specified search criteria
        /// </summary>
        private void ProcessSearch()
        {
            try
            {
                annunciator.Message = string.Empty;
                annunciator.Title = string.Empty;

                CommonSearchContext searchContext =
                    cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Page.Request.Url.ToString());

                if (FiscalYear != Convert.ToInt16(searchCriteria[ViewByFiscalYear]))
                {
                    FiscalYear = Convert.ToInt16(searchCriteria[ViewByFiscalYear]);
                }

                if (searchCriteria.Version != SearchCriteriaVersion)
                {
                    CurrentPageIndex = 0;
                    SearchCriteriaVersion = searchCriteria.Version;
                    ResultsCache.PurgeObject(cachePolicy);
                }

                PersonnelSalariesInstance.Search(searchCriteria, JobMapId);

                LoadDataGrid();
                ManagePagination();

                hiddenSearchCriteria.Value = HttpUtility.UrlEncode(AddRefreshDatesToCriteria(((CommonSearchContext) cachePolicy.GetCachedObject(CommonSearchContext.CacheKey)).GetSearchCriteria(Page.Request.Url.ToString())));
            }
            catch (Exception ex)
            {
                salaryGridDetails.Visible = pagerBelowDatagrid.Visible = pagerAboveDatagrid.Visible = reportDownload.Visible = false;
                annunciator.Message = Utility.ExceptionReport.GetExceptionInfo(ex, false);
            }
        }

        #endregion

        #region Web Form Designer generated code

        /// <summary>
        /// Handler for the event raised when the page is being initialized.
        /// Retrieve the page cache policy in force.
        /// Deposit event handlers to support the datagrid pagination.
        /// </summary>
        /// <param name="e">Argument associated with the event</param>
        protected override void OnInit(EventArgs e)
        {
            InitializeComponent();
            base.OnInit(e);
            cachePolicy = (Policy.ICachePolicy) Session[Policy.Names.CachePolicyKey];
            pageCachePolicy = (Policy.ICachePolicy) Session[Policy.Names.PageCachePolicyKey];

            pagerAboveDatagrid.FirstPage += new CommandEventHandler(this.OnFirstPage);
            pagerAboveDatagrid.LastPage += new CommandEventHandler(this.OnLastPage);
            pagerAboveDatagrid.NextPage += new CommandEventHandler(this.OnNextPage);
            pagerAboveDatagrid.PreviousPage += new CommandEventHandler(this.OnPreviousPage);

            pagerBelowDatagrid.FirstPage += new CommandEventHandler(OnFirstPage);
            pagerBelowDatagrid.LastPage += new CommandEventHandler(OnLastPage);
            pagerBelowDatagrid.NextPage += new CommandEventHandler(OnNextPage);
            pagerBelowDatagrid.PreviousPage += new CommandEventHandler(OnPreviousPage);
        }

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.insightHeader.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnHeaderNavigate);
            this.personnelSubNavigation.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnSubHeaderNavigate);
            this.breadCrumb.Navigate += new System.Web.UI.WebControls.CommandEventHandler(this.OnBreadCrumbNavigate);
            this.salaryGridDetails.ItemCreated += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemCreated);
            this.salaryGridDetails.ItemCommand += new System.Web.UI.WebControls.DataGridCommandEventHandler(this.OnDataGridItemCommand);
            this.salaryGridDetails.SortCommand += new System.Web.UI.WebControls.DataGridSortCommandEventHandler(this.OnSort);
            this.salaryGridDetails.ItemDataBound += new System.Web.UI.WebControls.DataGridItemEventHandler(this.OnItemDataBound);
        }

        #endregion
    }
}